
import os
import sys
import re
import subprocess
import pptx
import pandas
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel, QFileDialog, \
    QTextBrowser, QDesktopWidget, QLineEdit, QHBoxLayout, QRadioButton
from PyQt5.QtGui import QFont, QIcon


class PPTFilterGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('PPT教材自动筛选工具v3.2')
        self.setWindowIcon(QIcon('E:\P13_PptFilterUtil\icon.ico'))
        self.setGeometry(100, 100, 400, 200)
        self.setStyleSheet(
            "QMainWindow { background-color: #f0f0f0; }"
            "QWidget { font-family: '微软雅黑'; }"
        )
        font = QFont()
        font.setPointSize(14)
        self.setFont(font)

        # 获取屏幕的几何信息
        screen_geometry = QDesktopWidget().screenGeometry()
        # 计算窗口的位置使其居中
        window_width = self.frameGeometry().width()
        window_height = self.frameGeometry().height()
        x = (screen_geometry.width() - window_width) / 2
        y = (screen_geometry.height() - window_height) / 2
        self.move(int(x), int(y))

        # 设置mianWidget
        self.mainWidget = QWidget()
        self.setCentralWidget(self.mainWidget)
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)

        # 编写代码UI
        self.maininfoLabel = QLabel('根据关键词完成PPT教材筛选，一键生成定制化教材',  self)
        self.maininfoLabel.setStyleSheet('color: #7171C6; font-size: 18px; font-weight: bold;')
        self.mainLayout.addWidget(self.maininfoLabel)

        self.text_label2 = QLabel('--------')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)


        self.text_label2 = QLabel('1. 选择需要处理的PPT教材：')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)

        self.browseButton = QPushButton('浏览PPT教材', self)
        self.browseButton.clicked.connect(self.BrowsePPT)
        # self.browseButton.setFixedSize(200, 30)  # 设置宽度为120，高度为40
        self.mainLayout.addWidget(self.browseButton)

        self.text_label2 = QLabel('--------')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)

        self.text_label2 = QLabel('2. 输入需要完全保留的章节名：')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)
        # 添加要完全保留的章节名输入框
        self.keepchapter = QLineEdit(self)
        self.keepchapter.setPlaceholderText("输入章节名，以分号结尾，多个章节名以分号分隔")
        self.mainLayout.addWidget(self.keepchapter)

        self.text_label2 = QLabel('--------')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)

        self.text_label = QLabel('3. 输入过滤教材关键词：')
        self.text_label.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label)
        # 添加keywords输入框
        self.keywords = QLineEdit(self)
        self.keywords.setPlaceholderText("输入关键词，以分号结尾，多个关键词以分号分隔")
        self.mainLayout.addWidget(self.keywords)

        # 添加读取Excel格式关键词清单
        self.browseButton = QPushButton('浏览关键词清单Excel文件', self)
        self.browseButton.clicked.connect(self.BrowseXlsx)
        # self.browseButton.setFixedSize(400, 30)
        self.mainLayout.addWidget(self.browseButton)

        self.text_label2 = QLabel('--------')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)

        # 是否考虑表格中的关键词选项
        self.text_label1 = QLabel('4. 是否考虑教材中表格包含的关键词：')
        self.text_label1.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label1)
        self.horizontalLayout1 = QHBoxLayout()
        self.mainLayout.addLayout(self.horizontalLayout1)
        self.notableCheckBox = QRadioButton('不考虑表格中关键词', self)
        self.notableCheckBox.setChecked(True)  # 默认勾选 "不考虑表格关键词"
        self.horizontalLayout1.addWidget(self.notableCheckBox)
        self.tableCheckBox = QRadioButton('考虑表格中关键词', self)
        self.horizontalLayout1.addWidget(self.tableCheckBox)

        self.text_label2 = QLabel('--------')
        self.text_label2.setStyleSheet('color: #383838; font-size: 12px; font-weight: bold;')
        self.mainLayout.addWidget(self.text_label2)

        # 添加一个启动按钮
        self.startButton = QPushButton('开始执行', self)
        self.startButton.clicked.connect(self.mianstartExtraction)
        self.mainLayout.addWidget(self.startButton)

        # ResultTextEdit
        self.mainResultTextEdit = QTextBrowser(self)
        self.mainResultTextEdit.setOpenExternalLinks(True)
        self.mainLayout.addWidget(self.mainResultTextEdit)

    # 编写open_floder函数
    def BrowsePPT(self):
        options = QFileDialog.Options()
        options |= QFileDialog.ReadOnly
        filePath, _ = QFileDialog.getOpenFileName(self, '选择PPT文件', '', 'PPT 文件 (*.pptx);;All Files (*)', options=options)
        if filePath:
            self.pptFilePath = filePath
            self.mainResultTextEdit.clear()
            # self.leftResultTextEdit.append(f'已选择的PPT文件: <a href="file:///{self.pptFilePath}">{self.pptFilePath}</a>')
            self.mainResultTextEdit.append(f'已选择的PPT文件: {self.pptFilePath}')
            # 清空所有输入项
            self.keywords.setText('')
            self.xlsxFilePath = ''
            self.keepchapter.setText('')


    def BrowseXlsx(self):
        options = QFileDialog.Options()
        options |= QFileDialog.ReadOnly
        filePath, _ = QFileDialog.getOpenFileName(self, '选择模板文件', '', '模板 文件 (*.xlsx);;All Files (*)', options=options)
        if filePath:
            self.xlsxFilePath = filePath
            # self.mainResultTextEdit.clear()
            # self.leftResultTextEdit.append(f'已选择的PPT文件: <a href="file:///{self.pptFilePath}">{self.pptFilePath}</a>')
            self.mainResultTextEdit.append(f'已选择的关键词Excel文件: {self.xlsxFilePath}')
        else:
            self.mainResultTextEdit.append('请选择文件！')

    def mianstartExtraction(self):
        try:
            # if hasattr(self, 'pptFilePath', 'wordFilePath'):
            if hasattr(self, 'pptFilePath') :
                self.mainResultTextEdit.append('\n文件处理中...')
                keywords = self.keywords.text()
                if hasattr(self, 'xlsxFilePath') and len(self.xlsxFilePath) > 0:
                    df = pandas.read_excel(self.xlsxFilePath)
                    # 从第二行开始，将每一行的值转换成字符串，并用分号分隔
                    excel_text = ';'.join([';'.join(row.astype(str)) for _, row in df.iloc[0:].iterrows()])
                    # 删除；nan，并去除末尾可能存在的分号
                    excel_text = excel_text.replace(";nan", "").strip(";")
                    if len(excel_text) != 0:
                        keywords = excel_text if len(keywords) == 0 else keywords + excel_text
                if len(keywords) == 0:
                    self.mainResultTextEdit.append('\n请输入关键词！')
                    return
                folder_path = PPTFilterUtil().output_keyword_slide(self.pptFilePath, keywords,self.keepchapter.text(),
                                                                   self.tableCheckBox.isChecked())
                # self.rightResultTextEdit.append(f'\n输出文件夹: <a href="file:///{folder_path}">{folder_path}</a>')
                self.mainResultTextEdit.append(f'\n输出文件: {folder_path}')
                # 打开文件夹
                subprocess.Popen(['explorer', os.path.abspath(os.path.dirname(folder_path))],
                                 shell=True)  # Windows 上使用 "explorer"

            else:
                self.mainResultTextEdit.append('\n请先选择一个PPT教材文件！')
        except Exception as e:
            self.mainResultTextEdit.append('\n请确认PPT教材可编辑！')
            self.mainResultTextEdit.append(str(e))

class PPTFilterUtil:
    def __init__(self):
        # 继承父类的方法
        super().__init__()

    def output_keyword_slide(self, input_ppt, keywords, chapters, contain_table):
        # keywords = keywords + ';课程内容'
        keywords = keywords.lower() + ';课程内容'
        # keywords = keywords.lower()
        prs = pptx.Presentation(input_ppt)
        page_number = len(prs.slides)
        page_indices_to_keep = [0, page_number - 1]
        in_chapter = False

        for idx, slide in enumerate(prs.slides):
            if idx in page_indices_to_keep:
                continue
            kill_page = True

            # 保留指定章节
            if len(chapters)>0:
                # 判断是不是章节页 :判断文本里面是否包含“课程内容”
                is_content = False
                for shape in slide.shapes:
                    if hasattr(shape, "text") and shape.text.strip():  # 检查文本框是否有文本
                        text = shape.text.lower()
                        if '课程内容' in text:
                            is_content = True
                            break

                if is_content:
                    in_chapter = False
                    # 拼接所有加粗的文本
                    boldtext = []
                    for shape in slide.shapes:
                        if hasattr(shape, "text") and shape.text.strip():  # 检查文本框是否有文本
                            for paragraph in shape.text_frame.paragraphs:
                                for run in paragraph.runs:
                                    if run.font.bold:
                                        boldtext.append(run.text)
                    bold = "".join(boldtext)
                    # 判断加粗文件是否在输入的条件里
                    for chapter in re.split(';|；', chapters):
                        if chapter == bold and chapter != '':
                            in_chapter = True


            if not in_chapter:
                for shape in slide.shapes:
                    if hasattr(shape, "text") and shape.text.strip():  # 检查文本框是否有文本
                        # 循环以；或;分隔的keywords
                        # for keyword in keywords.split(';'):
                        text = shape.text.lower()
                        for keyword in re.split(';|；', keywords):
                            if keyword in text and keyword != '':
                                kill_page = False
                                break
                # v3.0 新增备注中关键词过滤
                notes = slide.notes_slide.notes_text_frame.text
                for keyword in re.split(';|；', keywords):
                    if keyword in notes:
                        kill_page = False
                        break

                # v3.0 新增表格中关键词过滤
                if contain_table:
                    table_text = self.extract_table_text(slide)
                    for keyword in re.split(';|；', keywords):
                        if keyword in table_text:
                            kill_page = False
                            break
            else:
                kill_page = False

            # 参考文档：https://blog.csdn.net/rekung/article/details/125504448
            # if kill_page and idx not in (0, page_number - 1):
            if kill_page:
                # 关键代码这里，不按索引进行删除，而是按xpath
                slis = (prs.slides._sldIdLst)
                _self = slis.xpath("p:sldId[@id='" + str(slide.slide_id) + "']")[0]
                slis.remove(_self)

        # 获取文件名
        file_name = input_ppt.split('/')[-1]
        # 将文件名中的"_done"替换为新的文件名
        output_ppt_name = file_name.replace('.pptx', '_done.pptx')
        # 组合路径和新的文件名
        output_ppt = '/'.join(input_ppt.split('/')[:-1]) + '/' + output_ppt_name

        prs.save(output_ppt)
        return output_ppt


    # 定义方法，提取表格中文字
    def extract_table_text(self, slide):
        table_texts = []
        for shape in slide.shapes:
            if shape.has_table:
                table = shape.table
                for row in table.rows:
                    for cell in row.cells:
                        cell_text = ''
                        for paragraph in cell.text_frame.paragraphs:
                            cell_text += paragraph.text
                        table_texts.append(cell_text)
        return table_texts

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = PPTFilterGUI()
    mainWindow.show()
    sys.exit(app.exec_())

